package cn.hoichun.news.Controller;

import cn.hoichun.news.Domain.Article;
import cn.hoichun.news.Domain.Page;
import cn.hoichun.news.Domain.User;
import cn.hoichun.news.Service.IArticleService;
import cn.hoichun.news.Service.IScoreService;
import cn.hoichun.news.Service.IUserService;
import com.qianxinyao.analysis.jieba.keyword.Keyword;
import com.qianxinyao.analysis.jieba.keyword.TFIDFAnalyzer;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author Hoichun
 */
@Controller
@RequestMapping("/News")
public class NewsController {
    private HashMap<String, List<Article>> primaryMap = new HashMap<>();
    private HashMap<String, List<Article>> secondaryMap = new HashMap<>();
    private static final TFIDFAnalyzer TFIDF_ANALYZER = new TFIDFAnalyzer();

    private final IUserService userService;
    private final IArticleService articleService;
    private final IScoreService scoreService;

    public NewsController(IUserService userService, IArticleService articleService, IScoreService scoreService) {
        this.userService = userService;
        this.articleService = articleService;
        this.scoreService = scoreService;
    }

    @RequestMapping("/index")
    String listUser(Model model) {
        List<User> userList = userService.listAllUsers();
        model.addAttribute("userList", userList);
        return "index";
    }

    @RequestMapping("/articleView")
    String articleViewAction(int articleId, int userId, Model model) {
        model.addAttribute("user", userService.findUserById(userId))
                .addAttribute("article", articleService.getArticleById(articleId))
                .addAttribute("score", scoreService.getScore(userId, articleId))
                .addAttribute(
                        "recommendList",
                        cache(articleService.getArticleKeyword(articleId), "indexWord", "tfidf", 10, articleId)
                );
        return "article_view";
    }

    @RequestMapping("/Score")
    String scoreAction(int userId, int articleId, int interest, int quality) {
        scoreService.addScore(userId, articleId, interest, quality);
        return "redirect:articleView?userId=" + userId + "&articleId=" + articleId;
    }

    @RequestMapping("/articleSearch")
    String articleSearch(
            int userId,
            @RequestParam(name = "searchWord", defaultValue = "") String searchWord,
            Model model,
            @RequestParam(name = "pageSize", defaultValue = "15") int pageSize,
            @RequestParam(name = "pageNum", defaultValue = "1") int pageNum,
            String searchMethod,
            @RequestParam(name = "orderMethod", defaultValue = "freqs") String orderMethod
    ) {
        long startTime = System.currentTimeMillis();
        List<Article> articleList;
        if ("".equals(searchWord)) {
            articleList = articleService.getRandomArticles(pageSize);
        } else {
            articleList = cache(searchWord, searchMethod, orderMethod, 0, 0);
        }
        model.addAttribute("guessList", articleService.getArticlesByUserMatrix(userId))
                .addAttribute("user", userService.findUserById(userId))
                .addAttribute("pageInfo", new Page<>(articleList, pageNum, pageSize))
                .addAttribute("searchWord", searchWord)
                .addAttribute("searchMethod", searchMethod)
                .addAttribute("orderMethod", orderMethod)
                .addAttribute("similarUser", userService.getSimilarUsers(userId))
                .addAttribute("time", (System.currentTimeMillis() - startTime) / 1000.0);
        return "article_list";
    }

    List<Article> cache(String searchWord, String searchMethod, String orderMethod, int size, int articleId) {
        final String like = "like";
        final String indexWord = "indexWord";
        final String fulltext = "fulltext";

        List<Article> articleList = new ArrayList<>();
        List<String> wordList = new ArrayList<>();
        for (Keyword word :
                TFIDF_ANALYZER.analyze(searchWord, 10000000)
        ) {
            wordList.add(word.getName());
        }
        if (wordList.size() > 0) {
            //primary缓存命中
            int mapSize = 10;
            if (primaryMap.containsKey(wordList + searchMethod + orderMethod)) {
                articleList = primaryMap.get(wordList + searchMethod + orderMethod);
                //secondary缓存命中
            } else if (secondaryMap.containsKey(wordList + searchMethod + orderMethod)) {
                articleList = secondaryMap.get(wordList + searchMethod + orderMethod);
                //primary缓存未满
                if (primaryMap.size() < mapSize) {
                    primaryMap.put(wordList + searchMethod + orderMethod, articleList);
                    secondaryMap.remove(wordList + searchMethod + orderMethod);
                } else {
                    //primary缓存已满
                    HashMap<String, List<Article>> tempMap = primaryMap;
                    primaryMap = secondaryMap;
                    secondaryMap = tempMap;
                }//primary和secondary均未命中
            } else {
                //查找数据库
                if (like.equals(searchMethod)) {
                    articleList = articleService.searchArticlesUsingLike(wordList);
                } else if (indexWord.equals(searchMethod)) {
                    articleList = articleService.searchArticlesUsingIndexWordOderBy(
                            wordList,
                            orderMethod,
                            size,
                            articleId
                    );
                } else if (fulltext.equals(searchMethod)) {
                    articleList = articleService.searchArticlesUsingFulltextIndex(searchWord);
                }
                //secondary未满，先放secondary
                if (secondaryMap.size() < mapSize) {
                    secondaryMap.put(wordList + searchMethod + orderMethod, articleList);
                    // secondary已满，primary未满
                } else if (primaryMap.size() < mapSize) {
                    primaryMap.put(wordList + searchMethod + orderMethod, articleList);
                } else {// secondary已满，primary已满
                    secondaryMap.clear();
                    secondaryMap.put(wordList + searchMethod + orderMethod, articleList);
                }
            }
        }
        return articleList;
    }
}